package com.gadgets.cm01.user.controller.impl;

import com.alibaba.fastjson.JSON;
import com.gadgets.cm01.common.GadgetsCm01Constant;
import com.gadgets.cm01.common.GadgetsCm01ExceptionConstant;
import com.gadgets.cm01.role.dto.UserRoleQueryDTO;
import com.gadgets.cm01.role.pojo.Role;
import com.gadgets.cm01.role.service.IRoleUserAllocationService;
import com.gadgets.cm01.user.controller.IUserLoginContoller;
import com.gadgets.cm01.user.dto.UserChangePwdDTO;
import com.gadgets.cm01.user.dto.UserInfoOperationDTO;
import com.gadgets.cm01.user.dto.UserLoginDTO;
import com.gadgets.cm01.user.dto.UserLoginReturnDTO;
import com.gadgets.cm01.user.exception.GadgetsUserInitException;
import com.gadgets.cm01.user.pojo.User;
import com.gadgets.cm01.user.service.IUserLoginService;
import com.gadgets.cm01.user.service.IUserOperationService;
import com.gadgets.framework.common.constant.ExceptionEnum;
import com.gadgets.framework.common.constant.GadgetsConstant;
import com.gadgets.framework.common.dto.HttpBaseResp;
import com.gadgets.framework.common.exception.GadgetsException;
import com.gadgets.framework.common.exception.GadgetsServiceException;
import com.gadgets.framework.common.repository.ISequeue;
import com.gadgets.framework.common.util.CacheUtils;
import com.gadgets.framework.common.util.DigestUtil;
import com.gadgets.framework.common.util.NumberFormatUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.List;

/**
 * @author UncleXiu
 * @version V1.0.0
 * @data 2020-09-16
 * 
 */
@RestController
@RequestMapping(method = {org.springframework.web.bind.annotation.RequestMethod.POST,org.springframework.web.bind.annotation.RequestMethod.GET},value = "/userLogin")
public class UserLoginController implements IUserLoginContoller {

    @Autowired
    @Qualifier(value = "userLoginServiceImpl")
    private IUserLoginService userLoginService;
    @Autowired
    @Qualifier(value = "userOperationServiceImpl")
    private IUserOperationService userOperationService;
    @Autowired
    @Qualifier(value = "roleUserAllocationServiceImpl")
    private IRoleUserAllocationService roleUserAllocationService;
    @Autowired
    private CacheUtils cacheUtils;
    @Autowired
    private ISequeue sequeue;

    /**
     * 用户登录/退出登录
     *
     * @param request      请求信息
     * @param response     应答信息
     * @param userLoginDTO 登录信息
     * @throws GadgetsServiceException 异常信息
     */
    @Override
    @RequestMapping(method = {org.springframework.web.bind.annotation.RequestMethod.POST,org.springframework.web.bind.annotation.RequestMethod.GET},value = "/baseLogin.do")
    public HttpBaseResp userLogin(HttpServletRequest request, HttpServletResponse response, UserLoginDTO userLoginDTO) throws GadgetsException {
        String sessionId = null;
        HttpBaseResp resp = new HttpBaseResp<>();
        if(null!=request.getAttribute(GadgetsConstant.USER_SESSION_ID_KEY)) {
            sessionId = request.getAttribute(GadgetsConstant.USER_SESSION_ID_KEY).toString();
        }else {
            sessionId = NumberFormatUtil.formatSeqNo(sequeue.getSequeueNoFromAim("sessionId"));
            HttpSession session = request.getSession(true);
            session.setAttribute("sessionId",sessionId);
            response.addCookie(new Cookie(GadgetsConstant.USER_SESSION_ID_KEY,sessionId));
        }
        if(GadgetsCm01Constant.LOGIN_OPER_LOGININ.equals(userLoginDTO.getOperType())){
            // 登录操作
            UserInfoOperationDTO operationDTO = new UserInfoOperationDTO();
            User user = userLoginService.loginIn(request, response, userLoginDTO);
            if(!user.getUserPassword().equals(DigestUtil.digestBySHA2_512(userLoginDTO.getUserPassword()))){
                // 密码错误次数+1，且判断是否需要变更用户状态
                operationDTO.setUserId(user.getId());
                operationDTO.setAfterStatus(GadgetsCm01Constant.USER_STATUS.USER_STATUS_FROZEN);
                operationDTO.setOperationType(GadgetsCm01Constant.USER_STATUS_OPER_TYPE.ADD_PWD_ERROR_TM);
                // 密码错误次数+1使用独立的事务提交，无需和后续的缓存操作绑定在一起
                userLoginService.updateUserPwdTm(operationDTO);
                // 记录当前 Session 的错误次数
                Integer errorTm = cacheUtils.getAimCache(GadgetsConstant.CACHE_BLOCK.BLACK_IP_CACHE,sessionId,Integer.class);
                if(null==errorTm){
                    errorTm = -1;
                }
                cacheUtils.putAimCache(GadgetsConstant.CACHE_BLOCK.BLACK_IP_CACHE,sessionId,++errorTm);
                throw new GadgetsServiceException(GadgetsCm01ExceptionConstant.USER_LOGIN_INFO_ERRROR,new Object[]{});
            }
            // 密码正确的情况下校验客户的状态
            Integer status = user.getUserStatus();
            if(GadgetsCm01Constant.USER_STATUS.USER_STATUS_INIT==status){
                // 如果用户是初始化状态，要求客户重置密码
                throw new GadgetsUserInitException(ExceptionEnum.NOTICE, GadgetsCm01ExceptionConstant.USER_PWD_NEED_INIT);
            }else if(GadgetsCm01Constant.USER_STATUS.USER_STATUS_ACTIVE==status){
                // 登录成功，重置用户密码错误次数，重置缓存
                operationDTO.setUserId(user.getId());
                operationDTO.setOperationType(GadgetsCm01Constant.USER_STATUS_OPER_TYPE.RESET_PWD_ERROR_TM);
                userLoginService.updateUserPwdTm(operationDTO);
                // 清除当前 Session 的错误次数
                cacheUtils.evictAimCache(GadgetsConstant.CACHE_BLOCK.BLACK_IP_CACHE,sessionId);
                // 将用户的角色信息加入到缓存中
                HashMap<String,Object> sessionCache = new HashMap<>();
                UserRoleQueryDTO userRoleQueryDTO = new UserRoleQueryDTO();
                userRoleQueryDTO.setUserId(user.getId());
                List<Role> roleList = roleUserAllocationService.queryRoleInfoByCondition(userRoleQueryDTO,null);
                sessionCache.put(GadgetsConstant.SESSION_CACHE_KEY.ROLE_LIST,roleList);
                sessionCache.put(GadgetsConstant.SESSION_CACHE_KEY.USER_INFO, user);
                cacheUtils.putAimCache(GadgetsConstant.CACHE_BLOCK.SESSION_CACHE,sessionId,sessionCache);
                UserLoginReturnDTO returnDTO = new UserLoginReturnDTO();
                // 将用户号，用户名的JSON信息返回给前端
                returnDTO.setUserName(user.getUserName());
                returnDTO.setUserNo(user.getUserNo());
                returnDTO.setSessionId(sessionId);
                resp.setErrorMsg(JSON.toJSONString(returnDTO));
                return resp;
            }else {
                // 用户状态不正确
                throw new GadgetsServiceException(GadgetsCm01ExceptionConstant.USER_STATUS_ERROR,new Object[]{});
            }
        }else {
            // 登出操作
            cacheUtils.evictAimCache(GadgetsConstant.CACHE_BLOCK.SESSION_CACHE,sessionId);
            resp.setErrorMsg("退出成功");
            return resp;
        }
    }

    /**
     * 激活用户
     * @param request       请求信息
     * @param response      应答信息
     * @param changePwdDTO  密码修改信息
     */
    @Override
    @RequestMapping(method = {org.springframework.web.bind.annotation.RequestMethod.POST,org.springframework.web.bind.annotation.RequestMethod.GET},value = "/activeUser.do")
    public HttpBaseResp<Object> activeUser(HttpServletRequest request, HttpServletResponse response, UserChangePwdDTO changePwdDTO){
        changePwdDTO.setOperationType(GadgetsCm01Constant.USER_PWD_OPER_TYPE.ACTIVE_USER);
        changePwdDTO.setOldPassword(DigestUtil.digestBySHA2_512(changePwdDTO.getOldPassword()));
        changePwdDTO.setNewPassword(DigestUtil.digestBySHA2_512(changePwdDTO.getNewPassword()));
        userOperationService.updateUserPwdInfo(changePwdDTO);
        return new HttpBaseResp<>();
    }

}
